import { EventTouch, Size, Vec2, Vec3 } from "cc";
import { IVector2, LoadDir, Maths, Rectangle, Sets, Vector2, _gameType, _logic, _scene, _timer, _ui } from "../../../main/script/Main";
import { EGameType } from "../../../main/script/module/define/GameTypeDefine";
import { ELogicDataState, ILogicData } from "../../../main/script/module/define/LogicDefine";
import { Scene } from "../Scene";
import { CubeEntity } from "../entity/CubeEntity";
import { ISelectionEntityData, SelectionEntity } from "../entity/SelectionEntity";


const v2T = new Vec2()
const v2T2 = new Vector2()
const v3T = new Vec3()
const rectT = new Rectangle()
const sizeT = new Size()


export class TenSceneLogic {

    private _startData: ISelectionEntityData = null!

    private moveDragDatas: ILogicData[] = null!
    public selection: SelectionEntity = null!

    private get _scene() { return _scene.getCurrent<Scene>() }

    public create() {

        if (_gameType.type == EGameType.tenLevel)
            this._scene.entityMgr.createDrag()

        if (_logic.isTenGameType) {

            let _datas = _logic.ten.data.datas
            this._scene.startAnim(
                _datas.length,
                (_index) => {
                    let data = _datas[_index]
                    data.entity = this._scene.entityMgr.createCube(data, this._scene.animLoadDir.subCount(), 0)
                },
                (_indexs) => {
                    this._scene.getIndexs(_logic.ten.size_bottom, _indexs, _logic.size.x * _logic.size.y)
                    this._scene.getIndexs(_logic.size, _indexs, 0)
                },
                () => {
                    let _fn = () => {
                        for (let dataIndex = 0; dataIndex < _datas.length; dataIndex++) {
                            let _data = _datas[dataIndex]
                            _data.dataIndex = dataIndex
                            _data.entity.resetItemPos()
                            _data.entity._isLerpAnim = true
                        }
                        _ui.blockTouchEvent(false)
                    }
                    if (_gameType.type == EGameType.index) {
                        this._scene.isLoadComplete = true
                        _fn()
                    } else {
                        this._scene.animLoadDir2.count = 2
                        this._scene.animLoadDir2.onFinish = () => {
                            this._scene.isLoadComplete = true

                            // 更新index
                            Sets.sortMin(_datas, v => _logic.ten.getPosByIndex(v.index.x, v.index.y, v.isBottom ? _logic.ten.size_bottom : _logic.size))
                            _fn()

                            this._scene.guide(.1)
                        }

                        this.moveAnim(_logic.ten.size_bottom, _logic.size.x * _logic.size.y, this._scene.animLoadDir2.subCount())
                        this.moveAnim(_logic.size, 0, this._scene.animLoadDir2.subCount())
                    }
                }
            )
        }
    }

    public touchMove(e: EventTouch) {

        if (this._startData) {
            if (this._startData != this._scene.entityMgr.drag) {
                if ((this._startData as CubeEntity).data.state != ELogicDataState.card)
                    return
            }
            this._scene.getTouchPos(e)
            this._startData.setItemPos(this._scene.touchMovePos)

            // 找到可落下的位置
            if (this.moveDragDatas === null!) {

                this.moveDragDatas = _logic.ten.getDragDatas(this._startData)
                for (let v of this.moveDragDatas) {
                    v.entity.setDragTip(true)
                }
            }
        }

    }

    public touchClear() {
        if (this._startData) {
            this._startData.resetItemPos()
        }

        this._startData = null!

        if (this.moveDragDatas !== null!) {
            for (let v of this.moveDragDatas)
                v.entity.setDragTip(false)
        }
        this.moveDragDatas = null!
    }

    public touchEnd(e: EventTouch) {
        let _startData = this._startData

        let data = this.touchData(e)

        this.touchClear()
        if (!_startData)
            return

        if (data) {
            let drag = this._scene.entityMgr.drag
            let cubeEntity = data as CubeEntity
            if (data != drag) {
                if (!cubeEntity.data.entity)
                    return

                if (_gameType.type == EGameType.index) {
                    if (data == _startData)
                        cubeEntity.item.scaleAnim(.2, null!, !cubeEntity.item.hasVisible())
                    return
                }
            }
            let cubeData = cubeEntity.data

            // 拖动
            if (data != _startData) {
                this.removeSelection()
                if (data != drag && cubeData.state == ELogicDataState.none) {
                    // 下方
                    let downData = _logic.ten.getDownData(cubeData)

                    let isAdd = false
                    if (downData) {
                        if (downData.entity == _startData)
                            return
                        if (downData.state == ELogicDataState.card) {
                            if (!this.remove(downData.entity, _startData, this._scene.touchMovePos)) {
                                if (_startData == drag)
                                    if (downData.configId == _startData.getConfigId())
                                        isAdd = true
                            } else {
                                return
                            }
                        }

                        if (!isAdd) {
                            if (_startData == drag) {
                                if (downData.state == ELogicDataState.back
                                    || downData.state == ELogicDataState.card)
                                    isAdd = true
                            }
                        }

                    } else {
                        if (_startData == drag) {
                            isAdd = true
                        }
                    }

                    if (isAdd) {
                        this._scene.clearTips()
                        this._scene.guide()

                        cubeEntity.data.configId = _startData.getConfigId()
                        _logic.ten.changeState(cubeData, ELogicDataState.card)

                        cubeEntity.setPositionXY(this._scene.touchMovePos, false)
                        cubeEntity.resetItemPos()

                        if (_startData == drag) {
                            drag.resetItemPos(false)
                            _logic.ten.remove(null!, null!, drag)
                        }

                        if (downData) {
                            _logic.ten.changeState(downData, ELogicDataState.cardStatic)

                            this.remove(cubeEntity, downData.entity)
                        }

                    }
                }
                else {
                    this.remove(data, _startData, this._scene.touchMovePos)
                }
            }
            // 点击
            else {
                if (data != drag) {
                    if (cubeData.state != ELogicDataState.card) {
                        return
                    }
                }
                if (!this.selection) {
                    this.selection = this._scene.entityMgr.createSelection(data)
                } else {
                    let selection = this.selection.data
                    if (selection == data) {
                        return
                    }
                    this.removeSelection()
                    if (!this.remove(data, selection)) {
                        this.selection = this._scene.entityMgr.createSelection(data)
                    }
                }
            }

        }
    }

    public removeSelection() {
        if (this.selection) {
            this._scene.entityMgr.remove(this.selection)
            this.selection = null!
        }
    }

    public remove(data: ISelectionEntityData, data2: ISelectionEntityData, data2Pos?: IVector2, noDown?: CubeEntity) {
        let drag = this._scene.entityMgr.drag
        let cubeEntity = data as CubeEntity
        if (data != drag) {
            if (cubeEntity.data.state != ELogicDataState.card)
                return false
        }
        let selectionEntity = data2 as CubeEntity
        if (data2 != drag) {
            if (selectionEntity.data.state != ELogicDataState.card)
                return false
        }

        let configId = data.getConfigId()
        let configId2 = data2.getConfigId()
        if (_logic.ten.hasSame(configId, configId2)) {
            if (data == drag) {
                drag.remove()
                selectionEntity.remove(true)
                _logic.ten.remove(selectionEntity, null!, drag, noDown)
            }
            else if (data2 == drag) {
                drag.remove(null!, data2Pos)
                cubeEntity.remove(true)
                _logic.ten.remove(cubeEntity, null!, drag, noDown)
            }
            else {
                let isLeft = selectionEntity.data.rect.x < cubeEntity.data.rect.x
                selectionEntity.remove(isLeft)
                cubeEntity.remove(!isLeft)
                _logic.ten.remove(cubeEntity, selectionEntity, null!, noDown)
            }
            this._scene.removeComplete()

            return true
        }

        return false
    }

    public touchStart(e: EventTouch) {
        this._startData = this.touchData(e)
        if (this._startData)
            if (_gameType.type != EGameType.index) {
                if (this._startData.getConfigId() == -1)
                    this._startData = null!
            }

    }

    private moveAnim(size: Vector2, startIndex: number, animComplete: () => void) {
        let maxY = size.y
        if (maxY == 0) {
            animComplete()
            return
        }
        let _datas = _logic.ten.data.datas
        let ys: number[] = []

        for (let y = 0; y < maxY; y++)
            ys.push(_datas[y + startIndex].rect.center.y + 5)

        let endIndex = Maths.zeroToMax(maxY - 1, _gameType.curRandom.run())

        this._scene.entityMgr.createMoveAnim(ys, endIndex, size.x * _logic.cubeSize.width, () => {
            let scaleDir = new LoadDir(size.x, () => {

                let moveDir = new LoadDir(size.x * (maxY - endIndex), animComplete)
                // 移动到最上层面 
                for (let x = 0; x < size.x; x++) {
                    let dataIndex = _logic.ten.getPosByIndex(x, endIndex, size)
                    let data = _datas[dataIndex]
                    data.index.y = maxY - 1
                    _logic.ten.getIndexByAabbCenter(data)
                    data.entity.startMoveAnim(true, moveDir.subCount())
                }

                // 上面的移动下来
                for (let y = endIndex + 1; y < maxY; y++)
                    for (let x = 0; x < size.x; x++) {
                        let dataIndex = _logic.ten.getPosByIndex(x, y, size)
                        let data = _datas[dataIndex]

                        data.index.y--

                        _logic.ten.getIndexByAabbCenter(data)
                        data.entity.startMoveAnim(false, moveDir.subCount())
                    }

            })

            // 缩放动画
            let duration = .4
            for (let x = 0; x < size.x; x++) {
                let dataIndex = _logic.ten.getPosByIndex(x, endIndex, size)
                let data = _datas[dataIndex]
                data.configId = _logic.ten.onceCardIds.shift()
                _timer.once(this, () => {
                    data.entity.startScaleAnim(x / (size.x - 1) * duration, scaleDir.subCount(), false)
                }, x * .02)
            }

        })


    }

    private touchData(e: EventTouch): ISelectionEntityData {
        this._scene.getTouchPos(e)

        let drag = this._scene.entityMgr.drag
        if (drag)
            if (drag.rect.contains(this._scene.touchMovePos))
                return drag
        return this.pointInData(this._scene.touchMovePos)
    }


    private pointInData(point: IVector2) {

        let clickEntity: CubeEntity = null!

        let startDataId = this._startData ? this._startData.getConfigId() : -1

        if (startDataId > 0) {
            rectT.width = _logic.cubeSize.width
            rectT.height = _logic.cubeSize.height
            rectT.center = point
        }

        for (let data of _logic.ten.data.datas) {
            if (data.rect.contains(point))
                clickEntity = data.entity

            // 拖动 
            if (startDataId > 0) {
                if (data.state == ELogicDataState.card)
                    if (_logic.ten.hasSame(data.configId, startDataId))
                        if (data.rect.intersects(rectT))
                            return data.entity
            }
        }
        return clickEntity
    }
}